﻿namespace EasyWeb.Design
{
    using System;
    using System.Globalization;
    using System.Reflection;

    internal class EWLocalizableString
    {
        private string propertyName;
        private string propertyValue;
        private Type resourceType;
        private Func<string> cachedResult;

        public EWLocalizableString(string propertyName)
        {
            EWDebug.IsNotNullOrEmpty(propertyName, "propertyName");

            this.propertyName = propertyName;
        }

        public string Value
        {
            get { return this.propertyValue; }
            set
            {
                if (this.propertyValue != value)
                {
                    this.ClearCache();
                    this.propertyValue = value;
                }
            }
        }

        public Type ResourceType
        {
            get { return this.resourceType; }
            set
            {
                if (this.resourceType != value)
                {
                    this.ClearCache();
                    this.resourceType = value;
                }
            }
        }

        public string GetLocalizableValue()
        {
            if (this.cachedResult == null)
            {
                if (this.propertyValue == null || this.resourceType == null)
                {
                    this.cachedResult = (() => this.propertyValue);
                }
                else
                {
                    var property = this.resourceType.GetProperty(this.propertyValue, BindingFlags.FlattenHierarchy | BindingFlags.GetProperty | BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static);
                    var hasError = false;

                    if (!this.resourceType.IsVisible || property == null || property.PropertyType != typeof(string))
                    {
                        hasError = true;
                    }

                    if (hasError)
                    {
                        var exceptionMessage = string.Format(CultureInfo.CurrentCulture, "Cannot retrieve property '{0}' because localization failed. Type '{1}' does not contain a public static string property with the name '{2}'.", this.propertyName, this.resourceType.FullName, this.propertyValue);

                        this.cachedResult = () =>
                        {
                            throw new InvalidOperationException(exceptionMessage);
                        };
                    }
                    else
                    {
                        this.cachedResult = (() => (string)property.GetValue(null, null));
                    }
                }
            }

            return this.cachedResult();
        }

        private void ClearCache()
        {
            this.cachedResult = null;
        }
    }
}
